package contegor.scire.core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


/**
 * {@link TaskImpl} used to notify a {@link Modifiable} that it must rollback the transaction associated with it.
 * 
 * The consequences this {@link Task} generates are {@link UntrackExternalLink} that will be sent to
 * external {@link Container}s with {@link Identifiable}s no more pointed by {@link Link}s in the current
 * {@link Container} because they exists no more becuase the rollback.
 * 
 * @version $Revision$
 * @author  Héctor Cirbián Pousa
 */
public class RollBackTask extends TaskImpl<Void> implements WithConsequences<Void, Void> {
  private static final long serialVersionUID = 5139047627063975345L;

  private List<UntrackExternalLink> consequences;

  public RollBackTask(TaskId taskId, Id targetContainerId) {
    super(targetContainerId);
    this.setTaskId(taskId);
  }

  public RollBackTask(Id targetContainerId) {
    super(targetContainerId);
    consequences = null;
  }

  @Override
  public void process(Container targetContainer) throws MissingElementException, TransactionException {
    assert (returnPoint != null) && targetContainer.getId().equals(this.targetContainerId);
    if (targetContainer instanceof Modifiable) {
      List<Id> noMorePointed = ((Modifiable)targetContainer).rollback(this.taskId.getTransactionId());
      if (noMorePointed != null) {
        TaskId subTaskId = this.taskId;
        this.consequences = new ArrayList<UntrackExternalLink>(noMorePointed.size());
        for (Id id: noMorePointed)
          if (!Id.RAW_ROOT.isAncestorOf(id))
            this.consequences.add(new UntrackExternalLink(subTaskId = subTaskId.next(subTaskId == this.taskId), id.getParentId(), id.getLastIdFragment(), targetContainerId));
      }
    }
  }

  @Override
  public List<? extends Task<Void>> getConsequences() {
    return this.consequences;
  }

  @Override
  public List<? extends ReturnPoint<? super Void>> getConsequencesReturnPoints() {
    if ((this.consequences == null) || (this.consequences.size()==0))
      return Collections.emptyList();
    return new InfiniteSingletonList<ReturnPoint<? super Void>>(this.returnPoint, this.consequences.size());
  }
}